package org.windowkit.toolkit.frame;

import java.awt.Dimension;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;

import org.windowkit.toolkit.panel.AbstractPanel;

/**
 * @author Rich O'Connell
 */
public class Desktop extends JDesktopPane {
	/**
	 *
	 */
	private static final long serialVersionUID = -2763674484658675496L;
	private final Set<WindowGroup> children;
	private final GroupManager groupManager;

	public Desktop() {
		children = new HashSet<WindowGroup>();
		groupManager = new GroupManager(children);
	}


	private class Child {
		private BaseIFrame parent;
	}


	public WindowGroup launchWindow(final AbstractPanel view) {
		return launchWindowInt(null, view);
	}

	public void launchWindow(final WindowGroup group, final AbstractPanel view) {
		launchWindowInt(group, view);
	}
	public WindowGroup launchWindowInt(WindowGroup group, final AbstractPanel view) {


		BaseIFrame frame = new BaseIFrame(view.getTitle());

		frame.setContentPane(view);

		Dimension pref = view.requestDimesions();
		if (pref != null) {
			frame.setSize(pref);
		}
		else {
			frame.setSize(850, 500);
		}
		add(frame);

		frame.addInternalFrameListener(groupManager);


		if (group == null) {
			group = new WindowGroup(frame);
			children.add(group);
			frame.setLocation(20, 20);
		}
		else {
			group.addMember(frame);
			BaseIFrame owner = group.getOwner();
			frame.setLocation(owner.getX() + owner.getWidth() + 5, owner.getY());
		}
		groupManager.highlightGroup(group);

		frame.setVisible(true);
		return group;
	}

	/**
	 * Handles IFrame events for window groups.
	 * Takes care of closing entire group when the owner closes, as well as highlighting the windows
	 * of the current group.
	 */
	public static class GroupManager extends InternalFrameAdapter {

		private final Set<WindowGroup> groups;

		public GroupManager(final Set<WindowGroup> owningCollection) {
			this.groups = owningCollection;
		}

		@Override
		public void internalFrameClosed(final InternalFrameEvent e) {
			JInternalFrame src = e.getInternalFrame();
			WindowGroup owner = null;
			for (WindowGroup wg : groups) {
				// see if an owning window was closed,
				// if so remove from collection and close all group members
				if (src.equals(wg.getOwner())) {
					owner = wg;
					for (BaseIFrame mem : wg.getMembers()) {
						mem.dispose();
					}
					break;
				}
			}
			if (owner != null) {
				groups.remove(owner);
			}

		}

		@Override
		public void internalFrameActivated(final InternalFrameEvent e) {
			JInternalFrame src = e.getInternalFrame();
			WindowGroup active = null;

			for (WindowGroup wg : groups) {
				if (src.equals(wg.getOwner())) {
					active = wg;
					break;
				}
				for (BaseIFrame bif : wg.getMembers()) {
					if (src.equals(bif)) {
						active = wg;
						break;
					}
				}
				if (active != null) {
					break;
				}
			}
			highlightGroup(active);
		}

		/**
		 * Highlight all windows in the given group, and un-highlight all other groups.
		 * @param group
		 */
		protected void highlightGroup(final WindowGroup group) {
			for (WindowGroup wg : groups) {
				boolean highlight = group.equals(wg);
				wg.getOwner().setHighlight(highlight);
				for (BaseIFrame bif : wg.getMembers()) {
					bif.setHighlight(highlight);
				}
			}

		}


	}
}
